#pragma once
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <functional>
#include <memory>
#include <vector>
#include <pthread.h>

#include "/home/hrj/include/Log.hpp" // 用绝对路径更加的安全
namespace stlthreadpool
{
    using namespace LogModule;
    static const int default_thread_size = 5; //  默认创建五个线程作为线程池

    class isRunning
    {
    public:
        void set()
        {
            std::unique_lock<std::mutex> lock(_lock);
            _isrunning = true;
        }
        void reset()
        {
            std::unique_lock<std::mutex> lock(_lock);
            _isrunning = false;
        }

        bool isRun()
        {
            std::unique_lock<std::mutex> lock(_lock);
            return _isrunning == true;
        }
    private:
        bool _isrunning = false;
        std::mutex _lock;
    };
    using task_t = std::function<void()>;
    class threadpool
    {
    private:
        static void scheduleQueue(threadpool*self,const std::string& name)
        {
            // 通过生产者消费者模型不断地接取任务
            while (true)
            {
                task_t task;
                {
                    std::unique_lock<std::mutex> lock(self->_lock);
                    while (self->_tq.size() == 0)
                    {
                        self->_wait_num++;
                        // LOG(LogLevel::DEBUG) << "wait num " << self->_wait_num;
                        LOG(LogLevel::DEBUG) << name << " begin to sleep";
                        if(self->_isRunning == false) return;
                        // LOG(LogLevel::DEBUG) << "wait num : " << self->_wait_num;
                        self->_cond.wait(lock);
                        LOG(LogLevel::DEBUG) << name << "wake up";
                        self->_wait_num--;
                        if(self->_isRunning == false && self->_tq.size() == 0) return;
                    }
                    task = self->_tq.front();
                    self->_tq.pop();
                }
                task();
            }
            LOG(LogLevel::DEBUG) << name << "退出成功";
        }

        threadpool(int threadsize = default_thread_size)
        {
            for(int i = 0;i < threadsize;i++)
            {
                _tp.emplace_back(scheduleQueue, this,"thread" + std::to_string(i));
            }
            LOG(LogLevel::DEBUG) << "threadpool has been created";
        }
    public:
        // 单例模式
        static threadpool* getInstance(int num = default_thread_size)
        {
            return new threadpool(num);
        }
        template <class Func, class... Args>
        void enterQueue(Func &&func, Args &&...args)
        {
            task_t newtask = std::bind(std::forward<Func>(func), std::forward<Args>(args)...); // 将我们的新任务进行打
            {
                std::unique_lock<std::mutex> lock(_lock);
                _tq.push(newtask);
                LOG(LogLevel::DEBUG) << " wait threads number: " << _wait_num;
                if(_wait_num)
                    _cond.notify_all();
            }
        }


        void Stop()
        {
            _isRunning = false;
            if(_wait_num)
                _cond.notify_all();
            
            for(auto& thread : _tp)
            {
                thread.join();
            }
            LOG(LogLevel::DEBUG) << "threads join successfully";
        }

        
    private:
        std::vector<std::thread> _tp; // 线程池
        std::queue<task_t> _tq;       // 任务队列
        std::mutex _lock;
        std::condition_variable _cond;

        bool _isRunning = true;
        // isRunning _isrunning; // 状态
        int _wait_num = 0;
    };
}
// 通过c++11的库引入我们的线程池